﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace SharePointUsers
{
    public partial class CreateReportWizard : Form
    {
        #region Control Members
        public bool PropertyDataPending = false;
        public bool ScopeDataPending = false;
        public bool ReportDesignIsReady = false;
        public Report reportObj = null;
        public bool ReportObjectChanged = true;
        public bool ReportDesignContainsData = false;
        public HashSet<string> PropertiesDisplayNames = new HashSet<string>();
        #endregion
        public TreeView PointerToSPObjectsTree = null;
        public MainForm PointerToMainForm = null;
        public SPType SelectedObjType = SPType.Undefined;
        public List<string> SelectedProperties = new List<string>();
        public SerializableDictionary<SPType, List<string>> SelectedScopes = new SerializableDictionary<SPType, List<string>>();
        private const string FORM_TITLE = "Report Designer";
        
        //Prepare SPU object
        SPUmanager spuManagerObj = new SPUmanager();
        public CreateReportWizard()
        {
            InitializeComponent();
        }
        private void ResetPropertiesTree()
        {
            if (ReportDesignContainsData || ReportDesignIsReady)
            {
                //Reset tree view
                treeViewObjects.Nodes.Clear();
                TreeNode ListPropNode = new TreeNode("Properties");
                ListPropNode.Name = "Properties";
                TreeNode ListScopeNode = new TreeNode("Scope");
                ListScopeNode.Name = "Scope";
                TreeNode ListNode = new TreeNode("List", new TreeNode[] {
                ListPropNode,ListScopeNode});
                TreeNode WebPropNode = new TreeNode("Properties");
                WebPropNode.Name = "Properties";
                TreeNode WebScopeNode = new TreeNode("Scope");
                WebScopeNode.Name = "Scope";
                TreeNode WebNode = new TreeNode("Site", new TreeNode[] {
                ListNode,WebPropNode,WebScopeNode});
                TreeNode SitePropNode = new TreeNode("Properties");
                SitePropNode.Name = "Properties";
                TreeNode SiteScopeNode = new TreeNode("Scope");
                SiteScopeNode.Name = "Scope";
                TreeNode SiteNode = new TreeNode("Site Collection", new TreeNode[] {
                WebNode,
                SitePropNode,SiteScopeNode});
                TreeNode ContentDBPropNode = new TreeNode("Properties");
                ContentDBPropNode.Name = "Properties";
                TreeNode ContentDBScopeNode = new TreeNode("Scope");
                ContentDBScopeNode.Name = "Scope";
                TreeNode ContentDBNode = new TreeNode("Content Database", new TreeNode[] {
            SiteNode,
            ContentDBPropNode,ContentDBScopeNode});
                TreeNode WAPropNode = new TreeNode("Properties");
                WAPropNode.Name = "Properties";
                TreeNode WAScopeNode = new TreeNode("Scope");
                WAScopeNode.Name = "Scope";
                TreeNode WANode = new TreeNode("WepApplication", new TreeNode[] {
            ContentDBNode,
            WAPropNode,WAScopeNode});
                TreeNode FarmPropNode = new TreeNode("Properties");
                FarmPropNode.Name = "Properties";
                TreeNode FarmNode = new TreeNode("Farm", new TreeNode[] {
            WANode,
            FarmPropNode});
                treeViewObjects.Nodes.Add(FarmNode);
            
                //reset the display name hash set that enures uniqueness
                PropertiesDisplayNames.Clear();
            ReportObjectChanged = false;
            ReportDesignIsReady = false;
            ReportDesignContainsData = false;
            treeViewObjects.ExpandAll();
            }
        }
        private void buttonFinish_Click(object sender, EventArgs e)
        {
            if(ReportObjectChanged)
                reportObj = CreateReportObject();
            DataTable Data = Reporter.ExecuteReport(reportObj, treeViewObjects);
            //Set the filter settings to csv
            saveFileDialogMain.Filter = Helper.CSV_FILTER;
            if (saveFileDialogMain.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                try
                {
                    using (new HourGlass())
                    {
                        SPUmanager.WriteDataTableToFile(saveFileDialogMain.FileName, Data);
                        //Reporter.SaveToExcel(Data, saveFileDialogMain.FileName);
                    }
                    MessageBox.Show("The designed repot has been processed successfully and saved to the selected location",
                                    "Design a custom report - Save As ..", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
                catch (Exception Ex)
                {
                    MessageBox.Show("Error finalizing report" + string.Format("Error details:{0}, Call stack: {1}", Ex.Message, Ex.StackTrace),
                             "Finalize report design", MessageBoxButtons.OK, MessageBoxIcon.Error);

                }
            }
            ReportDesignIsReady = true;
            ReportObjectChanged = false;
        }
        private TreeNode GetObjectNode(TreeView ObjectsTree, SPType SPObjType, string NodeName)
        {
            TreeNode Location = null;
            switch (SPObjType)
            {
                case SPType.Farm:
                    Location = treeViewObjects.Nodes[0].Nodes[NodeName];
                    break;
                case SPType.WebApplication:
                    Location = treeViewObjects.Nodes[0].Nodes[0].Nodes[NodeName];
                    break;
                case SPType.SiteCollection:
                    Location = treeViewObjects.Nodes[0].Nodes[0].Nodes[0].Nodes[0].Nodes[NodeName];
                    break;
                case SPType.Site:
                    Location = treeViewObjects.Nodes[0].Nodes[0].Nodes[0].Nodes[0].Nodes[0].Nodes[NodeName];
                    break;
                case SPType.List:
                    break;
                case SPType.Item:
                    break;
                case SPType.Group:
                    break;
                case SPType.User:
                    break;
                case SPType.ContentDatabase:
                    Location = treeViewObjects.Nodes[0].Nodes[0].Nodes[0].Nodes[NodeName];
                    break;
                case SPType.Feature:
                    break;
                case SPType.Collection:
                    break;
                case SPType.Undefined:
                    break;
                default:
                    break;
            }
            return Location;
        }
        private Property[] GetObjectProperties(TreeView ObjectsTree, SPType spType)
        {
            TreeNode Node = GetObjectNode(ObjectsTree, spType, "Properties");
            Property[] Properties = new Property[0];
            if (Node == null) return Properties;
            Properties = new Property[Node.Nodes.Count];
            int i = 0;
            foreach (TreeNode prop in Node.Nodes)
            {
                Property NewProperty = (Property)prop.Tag;
                Properties[i++] = NewProperty;
            }
            return Properties;
        }
        private List<string> GetObjectScopes(TreeView ObjectsTree, SPType spType)
        {
            TreeNode Scope = GetObjectNode(ObjectsTree, spType, "Scope");
            List<string> scopesItems = new List<string>(Scope.Nodes.Count);
            foreach (TreeNode node in Scope.Nodes)
            {
                scopesItems.Add(node.Text);
            }
            return scopesItems;
        }
        private Report CreateReportObject()
        {
            SerializableDictionary<SPType, Property[]> Query = new SerializableDictionary<SPType, Property[]>();
            Property[] FarmProps = GetObjectProperties(treeViewObjects, SPType.Farm);
            Property[] WAProps = GetObjectProperties(treeViewObjects, SPType.WebApplication);
            Property[] ContentDBProps = GetObjectProperties(treeViewObjects, SPType.ContentDatabase);
            Property[] SiteProps = GetObjectProperties(treeViewObjects, SPType.SiteCollection);
            Property[] WebProps = GetObjectProperties(treeViewObjects, SPType.Site);
            //Property[] ListProps = GetObjectProperties(treeViewObjects, SPType.Farm);
            Query.Add(SPType.Farm, FarmProps);
            Query.Add(SPType.WebApplication,WAProps);
            Query.Add(SPType.ContentDatabase,ContentDBProps);
            Query.Add(SPType.SiteCollection,SiteProps);
            Query.Add(SPType.Site,WebProps);

            //Fill the scopes collection
            SerializableDictionary<SPType, List<string>> Scopes = new SerializableDictionary<SPType, List<string>>();
            Scopes[SPType.WebApplication] = GetObjectScopes(treeViewObjects, SPType.WebApplication);
            Scopes[SPType.ContentDatabase] = GetObjectScopes(treeViewObjects, SPType.ContentDatabase);
            Scopes[SPType.SiteCollection] = GetObjectScopes(treeViewObjects, SPType.SiteCollection);
            Scopes[SPType.Site] = GetObjectScopes(treeViewObjects, SPType.Site);
            Report ReportObj = new Report(Guid.NewGuid(), textBoxName.Text, textBoxDesc.Text,
                                          Query, Reporter.CURRENT_VER_MAJOR, Reporter.CURRENT_VER_MINOR);
            ReportObj.Scope = Scopes;
            ReportDesignIsReady = true;
            return ReportObj;
        }

        private void buttonSelectProperties_Click(object sender, EventArgs e)
        {
            PointerToMainForm.contextMenuStripPropertiesPicking.Enabled = true;
            PointerToMainForm.PickPropertiestoolStripMenuItem.Enabled = true;
            PointerToMainForm.PickingProperties = true;
            PointerToMainForm.Focus();
            PointerToMainForm.Show();
        }

        private void CreateReportWizard_Load(object sender, EventArgs e)
        {
            treeViewObjects.ExpandAll();
        }
        private void AddProperty(string ObjType, string PropertyName, string PropertyDisplayName, TreeNode Location)
        {
            Property PropObj = new Property();
            PropObj.Name = PropertyName;
            PropObj.DisplayName = ObjType + Reporter.PROP_NAME_SPLITTER + PropertyDisplayName;
            PropObj.Properties = new SerializableDictionary<string, string>();
            AddProperty(PropObj, Location);
        }
        private void AddProperty(string PropertyName, string PropertyDisplayName, TreeNode Location)
        {
            Property PropObj = new Property();
            PropObj.Name = PropertyName;
            PropObj.DisplayName = PropertyDisplayName;
            PropObj.Properties = new SerializableDictionary<string, string>();
            AddProperty(PropObj, Location);
        }
        private void AddProperty(Property PropObj, TreeNode Location)
        {
            TreeNode newNode = Location.Nodes.Add(PropObj.DisplayName);
            newNode.Name = PropObj.Name;
            newNode.Checked = true;
            newNode.Tag = PropObj;
            PropertiesDisplayNames.Add(PropObj.DisplayName);
            Location.ExpandAll();
            //Reset control variables
            ReportObjectChanged = true;
            ReportDesignContainsData = true;
            ReportDesignIsReady = false;
            ValidateDesign();
        }
        private void AddScope(string Scope, TreeNode Location)
        {
            TreeNode newNode = Location.Nodes.Add(Scope);
            newNode.Name = Scope;
            newNode.Checked = true;
            Location.ExpandAll();
            //Reset control variables
            ReportObjectChanged = true;
            ReportDesignContainsData = true;
            ReportDesignIsReady = false;
            ValidateDesign();
        }
        private void AddSelectedProperties(List<string> Properties, SPType SPObjType)
        {
            bool PropertiesAdded = false;
            TreeNode Location = GetObjectNode(treeViewObjects, SPObjType, "Properties");
            if (Location == null) return;
            foreach (string Prop in Properties)
            {
                if(!Location.Nodes.ContainsKey(Prop))
                {
                    AddProperty(SPObjType.ToString(),Prop, Prop, Location);
                    PropertiesAdded = true;
                }
            }
            if (PropertiesAdded)
            {
                ReportDesignContainsData = true;
                ReportObjectChanged = true;
                ValidateDesign();
            }
            Location.ExpandAll();
        }
        private void AddSelectedScope(SerializableDictionary<SPType,List<string>> Scopes)
        {
            bool ScopesAdded = false;

            foreach (var Scope in Scopes)
            {
                TreeNode Location = GetObjectNode(treeViewObjects, Scope.Key, "Scope");
                if (Location == null) return;
                foreach (string scopeName in Scope.Value)
                {
                    if (!Location.Nodes.ContainsKey(scopeName))
                    {
                        AddScope(scopeName, Location);
                        ScopesAdded = true;
                        Location.ExpandAll();
                    }
                }
            }
            if (ScopesAdded)
            {
                ReportDesignContainsData = true;
                ReportObjectChanged = true;
                ValidateDesign();
            }
        }

        private void CreateReportWizard_Activated(object sender, EventArgs e)
        {
            if (PropertyDataPending)
            {
                PropertyDataPending = false;
                AddSelectedProperties(SelectedProperties, SelectedObjType);
            }
            else if (ScopeDataPending)
            {
                ScopeDataPending = false;
                AddSelectedScope(SelectedScopes);

            }
        }

        private void buttonNext_Click(object sender, EventArgs e)
        {
            if (tabControlReportDesigner.SelectedIndex < tabControlReportDesigner.TabCount)
            {
                buttonPrevious.Enabled = true;
                tabControlReportDesigner.SelectedIndex++;
                switch (tabControlReportDesigner.SelectedIndex)
                {
                    case 0:
                        ValidateBasic();
                        break;
                    case 1:
                        ValidateDesign();
                        break;
                    case 3:
                        ValidateFinalize();
                        break;
                    default:
                        break;
                }
            }
            

        }

        private void buttonPrevious_Click(object sender, EventArgs e)
        {
            if (tabControlReportDesigner.SelectedIndex > 0)
            {
                tabControlReportDesigner.SelectedIndex--;
                switch (tabControlReportDesigner.SelectedIndex)
                {
                    case 0:
                        ValidateBasic();
                        break;
                    case 1:
                        ValidateDesign();
                        break;
                    case 3:
                        ValidateFinalize();
                        break;
                    default:
                        break;
                }
                if(tabControlReportDesigner.SelectedIndex == 0)
                    buttonPrevious.Enabled = false;
            }
           
        }
        #region I\O Operations
        private void UpdateReportDesignFileName(string FileName)
        {
            //Get the file name only without the path
            int LastBackSlash = FileName.LastIndexOf("\\");
            string file = FileName.Substring(LastBackSlash + 1);
            this.Text = FORM_TITLE + " [" + file + "]";
        }
        private void buttonSaveReport_Click(object sender, EventArgs e)
        {
            if (!ReportDesignIsReady || (ReportDesignIsReady && ReportObjectChanged))
            {
                if (ReportDesignContainsData)
                {
                    reportObj = CreateReportObject();
                    ReportDesignIsReady = true;
                }
            }

            if(ReportDesignIsReady)
            {
                //Set the filter settings to report design
                saveFileDialogMain.Filter = Helper.REPORT_DESIGN_FILTER;
                saveFileDialogMain.FileName = textBoxName.Text;
                if (saveFileDialogMain.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                {
                    try
                    {
                        using (new HourGlass())
                        {
                            Reporter.SaveReportObject(reportObj, saveFileDialogMain.FileName);
                        }
                        MessageBox.Show("The report design has been saved successfully at the desired location",
                                        "Design a custom report - Save report design As ..", MessageBoxButtons.OK, MessageBoxIcon.Information);
                        UpdateReportDesignFileName(saveFileDialogMain.FileName);
                    }
                    catch (Exception Ex)
                    {
                        MessageBox.Show("Error saving report design. " + string.Format("Error details:{0}, Call stack: {1}", Ex.Message, Ex.StackTrace),
                                 "Save report design", MessageBoxButtons.OK, MessageBoxIcon.Error);

                    }
                }
            }
        }
        private void LoadReportDesign(string FileName)
        {
            //Load the 
            reportObj = Reporter.LoadReportObject(FileName);
            //Load report data on the form
            DisplayReportData(reportObj);
        }
        private void buttonLoadReportDesign_Click(object sender, EventArgs e)
        {
            bool LoadIsOKed = !ReportDesignContainsData;
            if (ReportDesignContainsData)
            {
                if (MessageBox.Show("You have query information already created in the wizard. Loading a report design will overwrite this information. Do you want to continue?",
                                    "Design a custom report - Save report design As ..", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Exclamation) == System.Windows.Forms.DialogResult.Yes)
                    LoadIsOKed = true;
            }
            if (!LoadIsOKed) return;
            //Set the filter of the dialog to report designer
            openFileDialogMain.Filter = Helper.REPORT_DESIGN_FILTER;
            if (openFileDialogMain.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                try
                {
                    using (new HourGlass())
                    {
                        LoadReportDesign(openFileDialogMain.FileName);
                    }
                    MessageBox.Show("The report design has been loaded successfully",
                                "Design a custom report - Load report design ...", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    UpdateReportDesignFileName(openFileDialogMain.FileName);
                    ReportObjectChanged = false;
                    ReportDesignIsReady = true;
                    ReportDesignContainsData = true;
                    ValidateBasic();
                    ValidateDesign();
                }
                catch (Exception Ex)
                {
                    MessageBox.Show("Error loading report design. " + string.Format("Error details:{0}, Call stack: {1}", Ex.Message, Ex.StackTrace),
                             "Load report design", MessageBoxButtons.OK, MessageBoxIcon.Error);

                }
            }
            
        }
        #endregion
        private void AddProperitesToTree(SerializableDictionary<SPType, Property[]> Query, SPType spType, TreeView treeView)
        {
            bool PropertiesAdded = false;
            TreeNode PropLocation = null;
            PropLocation = GetObjectNode(treeView, spType, "Properties");
            foreach (var Prop in Query[spType])
            {
                AddProperty(Prop, PropLocation);
                PropertiesAdded = true;
            }
            if (PropertiesAdded)
            {
                ReportDesignContainsData = true;
                ReportObjectChanged = true;
            }
        }
        
       
        private void DisplayReportData(Report ReportObj)
        {
            textBoxName.Text = ReportObj.Name;
            textBoxDesc.Text = ReportObj.Description;
            bool FarmPropertiesQuery = Reporter.HasQueryFor(ReportObj.Query, SPType.Farm);
            bool WebApplicationsQuery = Reporter.HasQueryFor(ReportObj.Query, SPType.WebApplication);
            bool ContentDBQuery = Reporter.HasQueryFor(ReportObj.Query, SPType.ContentDatabase);
            bool SiteCollectionsQuery = Reporter.HasQueryFor(ReportObj.Query, SPType.SiteCollection);
            bool WebQuery = Reporter.HasQueryFor(ReportObj.Query, SPType.Site);
            if (FarmPropertiesQuery)
            {
                AddProperitesToTree(ReportObj.Query, SPType.Farm, treeViewObjects);

            }
            if (WebApplicationsQuery)
            {
                AddProperitesToTree(ReportObj.Query, SPType.WebApplication, treeViewObjects);
            }
            if (ContentDBQuery)
            {
                AddProperitesToTree(ReportObj.Query, SPType.ContentDatabase, treeViewObjects);
            }
            if (SiteCollectionsQuery)
            {
                AddProperitesToTree(ReportObj.Query, SPType.SiteCollection, treeViewObjects);
            }
            //if (WebQuery)
            //{
            //    AppProperitesToTree(ReportObj.Query, SPType.Site, treeViewObjects);
            //}
            AddSelectedScope(ReportObj.Scope);


        }

        private void buttonResetQuery_Click(object sender, EventArgs e)
        {
            bool ResetIsOked = false;
            if (ReportDesignContainsData || ReportDesignIsReady)
            {
                if (MessageBox.Show("Are you sure you want to reset your query data? That is going to delete your properties selection. Do you want to continue?",
                    "Reset Query", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Exclamation) == System.Windows.Forms.DialogResult.Yes)
                    ResetIsOked = true;
            }
            if (ResetIsOked)
                ResetPropertiesTree();
            ValidateDesign();

        }

        private void textBoxName_TextChanged(object sender, EventArgs e)
        {
            ValidateBasic();
            if (reportObj != null)
            {
                reportObj.Name = textBoxName.Text;
            }
        }
        #region Validate settings

        private void ValidateBasic()
        {
            if (textBoxName.Text != "")
            {
                //Enable going to the next step once the name is in
                buttonNext.Enabled = true;
                //Enable saving the report once the name is in
                buttonSaveReport.Enabled = true;
            }
            else
            {
                buttonNext.Enabled = false;
            }
        }
        private void ValidateDesign()
        {
            if (PropertiesDisplayNames.Count <= 0)
            {
                ReportDesignContainsData = false;
                ReportDesignIsReady = false;
            }
            if (ReportDesignIsReady || ReportDesignContainsData)
            {
                buttonFinish.Enabled = true;
                buttonNext.Enabled = true;
                buttonSaveReport.Enabled = true;
            }
            else
            {
                buttonFinish.Enabled = false;
                buttonNext.Enabled = false;
            }
            
        }
        private void ValidateFinalize()
        {
            if (ReportDesignIsReady)
            {
                buttonPreview.Enabled = true;
                buttonFinish.Enabled = true;
                buttonNext.Enabled = false;
                buttonPrevious.Enabled = true;
            }
            else
            {
                buttonPreview.Enabled = false;
                buttonFinish.Enabled = false;
                buttonNext.Enabled = false;
            }
        }
        #endregion
        private void LoadPropertiesPage(Property SelectedProperty)
        {
            //Add display name
            listViewProperties.Items.Add("Display Name").SubItems.Add(SelectedProperty.DisplayName);

            //Add Name
            ListViewItem NameLVI = listViewProperties.Items.Add("Name");
            NameLVI.SubItems.Add(SelectedProperty.Name);
            NameLVI.BackColor = Color.LightGray;
            
            //Load properties page

            if (SelectedProperty.Properties != null)
            {
                foreach (var ValuePair in SelectedProperty.Properties)
                {
                    listViewProperties.Items.Add(ValuePair.Key).SubItems.Add(ValuePair.Value);
                }
            }
            listViewProperties.Sorting = SortOrder.Ascending;
            listViewProperties.Sort();
            
        }
        private void treeViewObjects_AfterSelect(object sender, TreeViewEventArgs e)
        {
            listViewProperties.Items.Clear();
            if (e.Node.Tag == null) return;
            if (e.Node.Tag.GetType() == typeof(Property))
            {
                Property NodeData = (Property)e.Node.Tag;
                LoadPropertiesPage(NodeData);

            }
            
        }
        private void UpdatePropertyValue(TreeNode PropertyNode,ListViewItem PropertyItem, string PropertyName, string NewValue, string OldValue)
        {
            Property NodeData = (Property)PropertyNode.Tag;
            //Handel special properties
            if (PropertyName == "DisplayName" || PropertyName == "Display Name")
            {
                NodeData.DisplayName = NewValue;
                //Update the tree node text
                PropertyNode.Text = NodeData.DisplayName;
                //Update the display names list
                //Remove old value
                PropertiesDisplayNames.Remove(OldValue);
                //Add the new value
                PropertiesDisplayNames.Add(NodeData.DisplayName);
            }
            else if (PropertyName == "Name")
            {
                NodeData.Name = NewValue;                
            }
            else
            {
                NodeData.Properties[PropertyName] = NewValue;
            }
            //Update the tree node tag data
            PropertyNode.Tag = NodeData;
            //Update properties list view
            PropertyItem.SubItems[1].Text = NewValue;
            //Reset control variables
            ReportObjectChanged = true;
        }
        private void UpdatePropertyValue(TreeNode PropertyNode, string PropertyName, string NewValue, string OldValue)
        {
            ListViewItem PropertyItem = null;
            PropertyItem = listViewProperties.FindItemWithText(PropertyName, false, 0);

            if (PropertyItem != null)
                UpdatePropertyValue(PropertyNode, PropertyItem, PropertyName, NewValue, OldValue);
        }
        private void EditPropertyNode(TreeNode PropertyNode)
        {
            if (PropertyNode != null)
            {
                Property PropertyObj = (Property)PropertyNode.Tag;
                Editor editorWindow = new Editor();
                editorWindow.textBoxName.ReadOnly = false;
                editorWindow.HasToBeUnique = true;
                editorWindow.PropertiesDisplayNames = PropertiesDisplayNames;
                editorWindow.labelValue.Text = "Display Name";
                editorWindow.Text = "Edit property";
                editorWindow.AddMode = true;
                editorWindow.OriginalValue = PropertyObj.DisplayName;
                editorWindow.OriginalName = PropertyObj.Name;
                editorWindow.textBoxName.Text = PropertyObj.Name;
                editorWindow.textBoxValue.Text = PropertyObj.DisplayName;
                editorWindow.textBoxName.BorderStyle = BorderStyle.Fixed3D;
                if (editorWindow.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                {
                    //Update values
                    if (editorWindow.ValueChanged)
                        UpdatePropertyValue(PropertyNode, "Display Name", editorWindow.textBoxValue.Text, editorWindow.OriginalValue);
                    UpdatePropertyValue(PropertyNode, "Name", editorWindow.textBoxName.Text, editorWindow.OriginalName);
                    ReportDesignIsReady = false;
                }
            }
        }
        private void EditPropertyListViewItem()
        {
            //Make sure the user selected on property only
            if (listViewProperties.SelectedItems.Count == 1)
            {
                //Make sure the property node is selected
                if (treeViewObjects.SelectedNode != null)
                {
                    if (treeViewObjects.SelectedNode.Tag == null) return;
                    if (treeViewObjects.SelectedNode.Tag.GetType() == typeof(Property))
                    {
                        Property NodeData = (Property)treeViewObjects.SelectedNode.Tag;
                        string PropertyName = listViewProperties.SelectedItems[0].Text;
                        string PropertyValue = listViewProperties.SelectedItems[0].SubItems[1].Text;

                        //Execlue system properties like Name
                        if (PropertyName != "Name")
                        {
                            Editor EditWindow = new Editor();
                            EditWindow.textBoxName.Text = PropertyName;
                            EditWindow.textBoxValue.Text = EditWindow.OriginalValue = PropertyValue;

                            EditWindow.PropertiesDisplayNames = PropertiesDisplayNames;
                            //Handel special properties like DisplayName
                            if (PropertyName == "Display Name")
                                EditWindow.HasToBeUnique = true;

                            if (EditWindow.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                            {
                                UpdatePropertyValue(treeViewObjects.SelectedNode, listViewProperties.SelectedItems[0], PropertyName, EditWindow.textBoxValue.Text, PropertyValue);
                            }
                        }

                    }
                }

            }
        }
        private void lsvProperties_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            EditPropertyListViewItem();
        }
        private void PopulatePreviewGrid(Report ReportObj)
        {
            DataTable reportStructure = Reporter.CreateDataTable(ReportObj.Query);
            dgvItems.DataSource = reportStructure;
        }
        private void tabControlReportDesigner_SelectedIndexChanged(object sender, EventArgs e)
        {
            switch (tabControlReportDesigner.SelectedIndex)
            {
                //case 0:
                //    ValidateBasic();
                //    break;
                //case 1:
                //    ValidateDesign();
                //    break;
                case 2:
                    if (ReportDesignContainsData)
                    {
                        try
                        {
                            using (new HourGlass())
                            {
                                //Make sure report is loaded
                                if (!ReportDesignIsReady)
                                    reportObj = CreateReportObject();
                                if (ReportDesignIsReady)
                                {
                                    buttonPreview.Enabled = false;
                                    listViewReportSettings.Items.Clear();
                                    PopulateReportSettings(reportObj);
                                }
                            }
                        }
                        catch (Exception Ex)
                        {
                            MessageBox.Show("Error loading report settings" + string.Format("Error details:{0}, Call stack: {1}", Ex.Message, Ex.StackTrace),
                                     "Load report settings", MessageBoxButtons.OK, MessageBoxIcon.Error);

                        }
                    }
                    break;
                case 3:
                    if (ReportDesignContainsData)
                    {
                        try
                        {
                            using (new HourGlass())
                            {
                                if (!ReportDesignIsReady)
                                    reportObj = CreateReportObject();
                                if (ReportDesignIsReady)
                                {
                                    PopulatePreviewGrid(reportObj);
                                }
                            }
                        }
                        catch (Exception Ex)
                        {
                            MessageBox.Show("Error loading report design structure" + string.Format("Error details:{0}, Call stack: {1}", Ex.Message, Ex.StackTrace),
                                     "Load report structure", MessageBoxButtons.OK, MessageBoxIcon.Error);

                        }
                    }
                    break;
                default:
                    break;
            }
        }
        private void PopulateReportSettings(Report ReportObj)
        {
            //Add public members
            listViewReportSettings.Items.Add("Name").SubItems.Add(ReportObj.Name);
            listViewReportSettings.Items.Add("Description").SubItems.Add(ReportObj.Description);
            listViewReportSettings.Items.Add("ID").SubItems.Add(ReportObj.ID.ToString());
            listViewReportSettings.Items.Add("Version Major").SubItems.Add(ReportObj.VersionMajor.ToString());
            listViewReportSettings.Items.Add("Version Minor").SubItems.Add(ReportObj.VersionMinor.ToString());

            //Load properties page

            if (ReportObj.Properties != null)
            {
                foreach (var ValuePair in ReportObj.Properties)
                {
                    listViewReportSettings.Items.Add(ValuePair.Key).SubItems.Add(ValuePair.Value);
                }
            }
            listViewReportSettings.Sorting = SortOrder.Ascending;
            listViewReportSettings.Sort();
        }
        private void buttonPreview_Click(object sender, EventArgs e)
        {
            try
            {
                using (new HourGlass())
                {
                    if (ReportObjectChanged)
                        reportObj = CreateReportObject();
                    DataTable Data = Reporter.ExecuteReport(reportObj, treeViewObjects);
                    dgvItems.DataSource = Data;
                }
                MessageBox.Show("The repot has been populated successfully ",
                                "Design a custom report - Preview data ..", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            catch (Exception Ex)
            {
                MessageBox.Show("Error processing report" + string.Format("Error details:{0}, Call stack: {1}", Ex.Message, Ex.StackTrace),
                         "Finalize report design", MessageBoxButtons.OK, MessageBoxIcon.Error);

            }

            ReportDesignIsReady = true;
            ReportObjectChanged = false;
        }

        private void listViewReportSettings_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            //Make sure the user selected on property only
            if (listViewReportSettings.SelectedItems.Count == 1)
            {
                string PropertyName = listViewReportSettings.SelectedItems[0].Text;
                string PropertyValue = listViewReportSettings.SelectedItems[0].SubItems[1].Text;


                    Editor EditWindow = new Editor();
                    EditWindow.textBoxName.Text = PropertyName;
                    EditWindow.textBoxValue.Text = EditWindow.OriginalValue = PropertyValue;

                   

                    if (EditWindow.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                    {
                        //Handel special properties like Name or Description, any property that is a member variable of the struct and not part of the property bag
                        if (PropertyName == "Name")
                        {
                            reportObj.Name = EditWindow.textBoxValue.Text;
                            textBoxName.Text = reportObj.Name;
                            //Update properties list view
                            listViewReportSettings.SelectedItems[0].SubItems[1].Text = reportObj.Name;
                            
                        }
                        else if (PropertyName == "Description")
                        {
                            reportObj.Description = EditWindow.textBoxValue.Text;
                            textBoxDesc.Text = reportObj.Description;
                            //Update properties list view
                            listViewReportSettings.SelectedItems[0].SubItems[1].Text = reportObj.Description;
                        }
                        else if (PropertyName == "ID")
                        {
                            try
                            {
                                reportObj.ID = new Guid(EditWindow.textBoxValue.Text);
                                //Update properties list view
                                listViewReportSettings.SelectedItems[0].SubItems[1].Text = reportObj.ID.ToString();
                            }
                            catch (Exception Ex)
                            {
                                MessageBox.Show("Unable to update the new ID" + string.Format("Error details:{0}, Call stack: {1}", Ex.Message, Ex.StackTrace),
                        "Updating the ID property of the report design", MessageBoxButtons.OK, MessageBoxIcon.Error);
                            }
                        }
                        else if (PropertyName == "Version Major")
                        {
                            try
                            {
                                reportObj.VersionMajor = int.Parse(EditWindow.textBoxValue.Text);
                                //Update properties list view
                                listViewReportSettings.SelectedItems[0].SubItems[1].Text = reportObj.VersionMajor.ToString();
                            }
                            catch (Exception Ex)
                            {
                                MessageBox.Show("Unable to update the new major version number" + string.Format("Error details:{0}, Call stack: {1}", Ex.Message, Ex.StackTrace),
                        "Updating the Major version property of the report design", MessageBoxButtons.OK, MessageBoxIcon.Error);
                            }
                        }
                        else if (PropertyName == "Version Minor")
                        {
                            try
                            {
                                reportObj.VersionMinor = int.Parse(EditWindow.textBoxValue.Text);
                                //Update properties list view
                                listViewReportSettings.SelectedItems[0].SubItems[1].Text = reportObj.VersionMinor.ToString();
                            }
                            catch (Exception Ex)
                            {
                                MessageBox.Show("Unable to update the new minor version number" + string.Format("Error details:{0}, Call stack: {1}", Ex.Message, Ex.StackTrace),
                       "Updating the minor version property of the report design", MessageBoxButtons.OK, MessageBoxIcon.Error);
                            }
                        }
                        else
                        {
                            if (reportObj.Properties != null)
                            {
                                reportObj.Properties[PropertyName] = EditWindow.textBoxValue.Text;
                            }
                        }
                        //Reset control variables
                        ReportObjectChanged = true;
                    }
                




            }
        }

        private void addPropertyToolStripMenuItem_Click(object sender, EventArgs e)
        {
            TreeNode SelectedNode = treeViewObjects.SelectedNode;

            if (SelectedNode != null)
            {
                Editor editorWindow = new Editor();
                editorWindow.textBoxName.ReadOnly = false;
                editorWindow.HasToBeUnique = true;
                editorWindow.PropertiesDisplayNames = PropertiesDisplayNames;
                editorWindow.labelValue.Text = "Display Name";
                editorWindow.Text = "Add new property";
                editorWindow.AddMode = true;
                editorWindow.textBoxName.BorderStyle = BorderStyle.Fixed3D;
                if (editorWindow.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                {
                    //Add value to the tree
                    AddProperty(editorWindow.textBoxName.Text, editorWindow.textBoxValue.Text, SelectedNode);

                }
            }
        }
        private void EnablePropertiesMenuItems(int PropertiesNodeCount)
        {
            addPropertyToolStripMenuItem.Visible = true;
            clearPropertiesToolStripMenuItem.Visible = false;
            if (PropertiesNodeCount > 0)
            {
                clearPropertiesToolStripMenuItem.Visible = true;

            }
            removePropertyToolStripMenuItem.Visible = false;
            editPropertyToolStripMenuItem.Visible = false;
            removeScopeToolStripMenuItem.Visible = false;
            addScopeToolStripMenuItem.Visible = false;
        }
        private void EnableScopeMenuItems(int ScopesNodeCount)
        {
            addScopeToolStripMenuItem.Visible = true;
            addPropertyToolStripMenuItem.Visible = false;
            clearPropertiesToolStripMenuItem.Visible = false;
            clearScopesToolStripMenuItem.Visible = false;
            if (ScopesNodeCount > 0)
            {
                clearScopesToolStripMenuItem.Visible = true;

            }
            removePropertyToolStripMenuItem.Visible = false;
            editPropertyToolStripMenuItem.Visible = false;
            removeScopeToolStripMenuItem.Visible = false;
        }
        private void contextMenuStripTree_Opening(object sender, CancelEventArgs e)
        {
            //Handle the menu openned from list view
            if (contextMenuStripTree.SourceControl.GetType() == typeof(ListView))
            {
                if (listViewProperties.Items.Count > 0 &&
                  listViewProperties.SelectedItems.Count > 0 &&
                    listViewProperties.SelectedItems[0].BackColor != Color.LightGray)
                {
                    removePropertyToolStripMenuItem.Visible = false;
                    editPropertyToolStripMenuItem.Visible = true;
                    addPropertyToolStripMenuItem.Visible = false;
                    clearPropertiesToolStripMenuItem.Visible = false;
                }
                else
                    e.Cancel = true;
            }
            else
            {
                //Make sure the user selected a properties node
                TreeNode SelectedNode = treeViewObjects.SelectedNode;
                if (SelectedNode != null)
                {
                    //If the "Properties" node is selected allow for add and bulk ops
                    if (SelectedNode.Text == "Properties")
                    {
                        EnablePropertiesMenuItems(SelectedNode.Nodes.Count);
                    }
                    else if (SelectedNode.Text == "Scope")
                    {
                        EnableScopeMenuItems(SelectedNode.Nodes.Count);
                    }
                    else if (SelectedNode.Parent != null && SelectedNode.Parent.Text == "Properties")
                    {
                        //Selected one of the properties
                        removePropertyToolStripMenuItem.Visible = true;
                        editPropertyToolStripMenuItem.Visible = true;
                        addPropertyToolStripMenuItem.Visible = false;
                        clearPropertiesToolStripMenuItem.Visible = false;
                    }
                    else if (SelectedNode.Parent != null && SelectedNode.Parent.Text == "Scope")
                    {
                        //Selected one of the scopes
                        removePropertyToolStripMenuItem.Visible = false;
                        editPropertyToolStripMenuItem.Visible = false;
                        addPropertyToolStripMenuItem.Visible = false;
                        clearPropertiesToolStripMenuItem.Visible = false;
                        removeScopeToolStripMenuItem.Visible = true;
                        clearScopesToolStripMenuItem.Visible = false;

                    }
                    //else
                    //{
                    //    //Selected an SP type object node, e.g.: Farm, Content DB ... etc.
                    //    //Move to the properties node and enable options
                    //    treeViewObjects.SelectedNode = SelectedNode.Nodes["Properties"];
                    //    EnablePropertiesMenuItems(SelectedNode.Nodes.Count);
                    //}
                    else
                        e.Cancel = true;
                }
            }
        }
        

        private void clearPropertiesToolStripMenuItem_Click(object sender, EventArgs e)
        {
            TreeNode SelectedNode = treeViewObjects.SelectedNode;
            if (SelectedNode != null)
            {
                foreach (TreeNode prop in SelectedNode.Nodes)
                {
                    //Remove the properties' display names from the hashlist that enusres uniqueness
                    PropertiesDisplayNames.Remove(((Property)prop.Tag).DisplayName);
                }
                SelectedNode.Nodes.Clear();
                ReportDesignIsReady = false;
                ValidateDesign();
            }
        }

        private void removePropertyToolStripMenuItem_Click(object sender, EventArgs e)
        {
            TreeNode SelectedNode = treeViewObjects.SelectedNode;
            if (SelectedNode != null)
            {
                //Remove the property's display name from the hashlist that enusres uniqueness
                PropertiesDisplayNames.Remove(((Property)SelectedNode.Tag).DisplayName);
                SelectedNode.Remove();
                ReportDesignIsReady = false;
                ValidateDesign();
            }
        }

        private void editPropertyToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //If the menu is triggered from the list view
            if (contextMenuStripTree.SourceControl.GetType() == typeof(ListView))
            {
                EditPropertyListViewItem();
            }
            else
            {//if the menu is triggered from the tree view
                TreeNode SelectedNode = treeViewObjects.SelectedNode;
                if (SelectedNode != null)
                {
                    EditPropertyNode(SelectedNode);
                }
            }
        }
       

        private void textBoxDesc_TextChanged(object sender, EventArgs e)
        {
            if (reportObj != null)
            {
                reportObj.Description = textBoxDesc.Text;
            }
        }

        private void buttonPickScope_Click(object sender, EventArgs e)
        {
            PointerToMainForm.contextMenuStripPropertiesPicking.Enabled = true;
            PointerToMainForm.PickPropertiestoolStripMenuItem.Enabled = true;
            PointerToMainForm.PickScopestoolStripMenuItem.Enabled = true;
            PointerToMainForm.PickScopestoolStripMenuItem.Visible = true;
            PointerToMainForm.PickingProperties = false;
            PointerToMainForm.PickingScopes = true;
            PointerToMainForm.Focus();
            PointerToMainForm.Show();
        }

        private void removeScopeToolStripMenuItem_Click(object sender, EventArgs e)
        {
            TreeNode SelectedNode = treeViewObjects.SelectedNode;
            if (SelectedNode != null)
            {
                SelectedNode.Remove();
                ReportDesignIsReady = false;
                ValidateDesign();
            }
        }

        private void clearScopesToolStripMenuItem_Click(object sender, EventArgs e)
        {
            TreeNode SelectedNode = treeViewObjects.SelectedNode;
            if (SelectedNode != null)
            {
                SelectedNode.Nodes.Clear();
                ReportDesignIsReady = false;
                ValidateDesign();
            }
        }

        private void addScopeToolStripMenuItem_Click(object sender, EventArgs e)
        {
            TreeNode SelectedNode = treeViewObjects.SelectedNode;

            if (SelectedNode != null)
            {
                Editor editorWindow = new Editor();
                editorWindow.textBoxName.ReadOnly = false;
                editorWindow.labelValue.Text = "Scope";
                editorWindow.Text = "Add new scope";
                editorWindow.AddMode = true;
                editorWindow.labelName.Visible = false;
                editorWindow.textBoxName.Visible = false;
                editorWindow.textBoxName.BorderStyle = BorderStyle.Fixed3D;
                editorWindow.labelValue.Left = 6;
                editorWindow.textBoxValue.Left = 47;
                editorWindow.textBoxValue.Width *= 2;
                if (editorWindow.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                {
                    //Add value to the tree
                    AddScope(editorWindow.textBoxValue.Text, SelectedNode);

                }
            }
        }
    }
}
